package cumeo89.chii.client.ui;

import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.DockPanel.DockLayoutConstant;

/**
 * TODO resize, collapse
 * 
 * @author cumeo
 */
public class FullWindowPanel extends ComplexPanel implements ResizeHandler {

	private Widget north;
	private Widget west;
	private Widget south;
	private Widget east;
	private Widget center;
	private int centerMinWidth;
	private int centerMinHeight;

	public FullWindowPanel() {
		setElement(DOM.createDiv());
		DOM.setStyleAttribute(getElement(), "position", "relative");
		DOM.setStyleAttribute(getElement(), "overflow", "hidden");
		Window.addResizeHandler(this);
		RootPanel.get().add(this);
	}

	@Override
	public void add(Widget child) {
		throw new UnsupportedOperationException(
				"Use add(Widget, Constraint) instead.");
	}

	public void add(Widget child, Constraint constraint) {
		// Checking and logical attach.
		if (constraint.direction == DockPanel.NORTH) {
			if (north != null) {
				remove(north);
			}
			north = child;
			child.setHeight(constraint.height + "px");
		} else if (constraint.direction == DockPanel.WEST) {
			if (west != null) {
				remove(west);
			}
			west = child;
			child.setWidth(constraint.width + "px");
		} else if (constraint.direction == DockPanel.SOUTH) {
			if (south != null) {
				remove(south);
			}
			south = child;
			child.setHeight(constraint.height + "px");
		} else if (constraint.direction == DockPanel.EAST) {
			if (east != null) {
				remove(east);
			}
			east = child;
			child.setWidth(constraint.width + "px");
		} else if (constraint.direction == DockPanel.CENTER) {
			if (center != null) {
				remove(center);
			}
			center = child;
			centerMinWidth = constraint.width;
			centerMinHeight = constraint.height;
		} else {
			throw new UnsupportedOperationException(
					"Direction is not supported.");
		}
		add(child, getElement());
		doLayout();
	}

	protected void doLayout() {
		setWidgetPosition(this, 0, 0);
		setSize(Window.getClientWidth() + "px", Window.getClientHeight() + "px");

		// Compute width.
		int width = centerMinWidth;
		if (west != null) {
			width += west.getOffsetWidth();
		}
		if (east != null) {
			width += east.getOffsetWidth();
		}
		if (width < Window.getClientWidth()) {
			width = Window.getClientWidth();
		}

		// Compute height.
		int height = centerMinHeight;
		if (north != null) {
			height += north.getOffsetHeight();
		}
		if (south != null) {
			height += south.getOffsetHeight();
		}
		if (height < Window.getClientHeight()) {
			height = Window.getClientHeight();
		}

		// Set children position.
		int availWidth = width, availHeight = height, availLeft = 0, availTop = 0;
		if (north != null) {
			north.setWidth(width + "px");
			setWidgetPosition(north, 0, 0);
			availTop += north.getOffsetHeight();
			availHeight -= north.getOffsetHeight();
		}
		if (south != null) {
			south.setWidth(width + "px");
			setWidgetPosition(south, 0, height - south.getOffsetHeight());
			availHeight -= south.getOffsetHeight();
		}
		if (west != null) {
			west.setVisible(true);
			west.setHeight(availHeight + "px");
			setWidgetPosition(west, 0, availTop);
			availLeft += west.getOffsetWidth();
			availWidth -= west.getOffsetWidth();
		}
		if (east != null) {
			east.setHeight(availHeight + "px");
			setWidgetPosition(east, width - east.getOffsetWidth(), availTop);
			availWidth -= east.getOffsetWidth();
		}
		if (center != null) {
			center.setWidth(availWidth + "px");
			center.setHeight(availHeight + "px");
			setWidgetPosition(center, availLeft, availTop);
		}
	}

	private void setWidgetPosition(Widget w, int left, int top) {
		Element elem = w.getElement();
		DOM.setStyleAttribute(elem, "position", "absolute");
		DOM.setStyleAttribute(elem, "left", left + "px");
		DOM.setStyleAttribute(elem, "top", top + "px");
	}

	@Override
	public boolean remove(Widget child) {
		boolean removed = super.remove(child);
		if (removed) {
			doLayout();
		}
		return removed;
	}

	// constraint
	public static class Constraint {
		public int width;
		public int height;
		public DockLayoutConstant direction;
		public boolean resizable;
		public boolean collapable;
	}

	public void onResize(ResizeEvent event) {
		doLayout();
	}

}
